package swing.ui;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.event.ChangeListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * A concrete tree-structured chooser based on an Swing <code>JTree</code>
 * controled with checkboxes on each node.
 * 
 * A chooser that allows to select a subset of a given set of elements. and to
 * order the selection
 * 
 * To using this class, call constructor with a tree of elements of
 * <code>SelectableTreeNode</code>. To get the selection, call
 * <code>getSelection()</code>.
 * 
 * Every node has three state, SELECTED, NOT_SELECTED and GRAY. Gray means it
 * has some children but <em>not</em> all selected.
 * 
 * To order the selection, click the eastest button in Header. Every
 * <code>isselectable</code> element can be ordered.
 * 
 * This control has 3 modus parameterized by <code>orderable</code> and
 * <code>showOrdering</code>. see also <code>Contructor</code>.
 * 
 * Example 1
 * 	<code>
 *     	SelectableTreeNode root = new SelectableTreeNode("Projecct");
 *		SelectableTreeNode ss1 = new SelectableTreeNode("Subsystem 1");
 *		root.add(ss1);
 *		SelectableTreeNode ss2 = new SelectableTreeNode("Subsystem 2");
 *		root.add(ss2);
 *		SelectableTreeNode factor1 = new SelectableTreeNode("factor1");
 *		SelectableTreeNode factor2 = new SelectableTreeNode("factor2");
 *		SelectableTreeNode factor3 = new SelectableTreeNode("factor3");
 *		SelectableTreeNode factor4 = new SelectableTreeNode("factor4");
 *		ss1.add(factor1);
 *		ss1.add(factor2);
 *		ss2.add(factor3);
 *		ss2.add(factor4);
 *		TreeChooserControl chooser = new TreeChooserControl(
 *											"Selection", "Ordering", root, true, true);
 *	</code>
 *
 * Example 2
 * <code>
 *      TreeChooserControl chooser = new TreeChooserControl("Selection", "Ordering");
 *      chooser.setAbstraction(abstraction);      
 * </code>
 * 
 * The method <code>chooser.getSelection()</code> returns selected nodes.
 * The method <code>chooser.getSelectedObjects()</code> returns objects in selected nodes.
 * 
 * @see de.consideo.gui.trees.SelectableTreeNode
 * @see de.consideo.gui.trees.SelectableTreeNodeRenderer
 * @see de.consideo.gui.trees.SelectableTreeNodeRenderer
 * @since 19/08/2005
 * @author Daoen Pan
 */
@SuppressWarnings("serial")
public class TreeChooserControl extends JComponent {
	// gui component
	private JScrollPane selectionScrollPane;
	private JTree selectionTree; // holds all elements
	private JPanel selectionHeaderPane;
	private JToolBar selectionToolBar;
	private JLabel selectionHeaderLabel;
	private String selectionHeader;

	private JScrollPane orderingScrollPane;
	private JTree orderingTree; // holds selected elements

	private JPanel orderingHeaderPane;
	private JToolBar orderingToolBar;
	private JLabel orderingHeaderLabel;
	private String orderingHeader;

	// buttons
	private JToggleButton toggle;
	private JButton moveUp;
	private JButton moveDown;
	private JButton moveRight;
	private JButton moveLeft;
	private JButton selectAll;
	private JButton deselectAll;

	private JPanel middleButtonPane;
	private JComponent presentation;

	private SelectableTreeNode root;
	private OrderingTreeModel orderingTreeModel;

	private boolean orderable;
	private boolean showOrdering;


	
	private JTextArea messageArea;

	/**
	 * Creates a checked tree chooser control 
	 * 
	 * @param selectionHeader
	 * 			the text of selection tree's header
	 * @param orderingHeader
	 * 			the text of ordering tree's header 
	 * @param root
	 * 			a <code>SelectableTreeNode</code> object 
	 * @param orderable		a boolean value
	 * @param showOrdering	a boolean value
	 * 
	 * 	   orderable showOrdering        control       				example
	 *  1.   false      false       selection functionality		  curve chooser
	 *  2.   false      true          illegal(same as 1) 
	 *  3.   true       false		2 control alternatively 
	 *  4.   true       true	    show 2 control                export chooser
	 */
	public TreeChooserControl(String selectionHeader, String orderingHeader,
			SelectableTreeNode root, boolean orderable, boolean showOrdering) {
		if (root != null)
			root.refresh();

		this.root = root;
		this.selectionHeader = selectionHeader;
		this.orderingHeader = orderingHeader;
		this.orderable = orderable;
		this.showOrdering = showOrdering;

		createPanels();
		createTrees(root);
		createPresentation();

		messageArea = new JTextArea();
		messageArea.setColumns(50);
		messageArea.setRows(10);
		messageArea.setEditable(false);
	}

	/**
	 * @see #TreeChooserControl(String, String, SelectableTreeNode, boolean, boolean)
	 */
	public TreeChooserControl(String selectionHeader, String orderingHeader,
			SelectableTreeNode root) {
		this(selectionHeader, orderingHeader, root, true, true);
	}

	/**
	 * @see #TreeChooserControl(String, String, SelectableTreeNode, boolean, boolean)
	 */
	public TreeChooserControl(String header, SelectableTreeNode root) {
		this(header, header, root, false, false);
	}

	/**
	 * @see #TreeChooserControl(String, String, SelectableTreeNode, boolean, boolean)
	 */
	public TreeChooserControl(SelectableTreeNode root) {
		this("Selection", root); //$NON-NLS-1$
	}

	/**
	 * @see #TreeChooserControl(String, String, SelectableTreeNode)
	 */
	public TreeChooserControl(String selectionHeader, String orderingHeader) {
		this(selectionHeader, orderingHeader, null);
	}

	/**
	 * Sets the abstraction for chooser
	 * 
	 * @param abstraction
	 *            the root of selection tree
	 */
	public void setAbstraction(Object abstraction) {
		if (abstraction instanceof SelectableTreeNode) {
			root = (SelectableTreeNode) abstraction;
			root.refresh();
			DefaultTreeModel model = (DefaultTreeModel) selectionTree
					.getModel();
			model.setRoot(root);
			orderingTreeModel = new OrderingTreeModel(root);
			orderingTree.setModel(orderingTreeModel);
		}
	}

	/**
	 * All nodes are setting selected.
	 */
	public void selectAll() {
		if (root != null) {
			setNodeSelected(root, true);
			updateMessageArea();
		}
	}

	/**
	 * clear the selection of all selected nodes.
	 */
	public void deselectAll() {
		if (root != null) {
			setNodeSelected(root, false);
			updateMessageArea();
		}
	}

	/**
	 * sets a font for this control
	 * 
	 * @param font
	 *            The new font
	 */
	public void setFont(Font font) {
		selectionTree.setFont(font);
		orderingTree.setFont(font);
		selectionHeaderLabel.setFont(font);
		orderingHeaderLabel.setFont(font);
	}

	/*
	 * @see de.consideo.gui.tools.ISelection#getSelection()
	 */
	public Object getSelection() {
		Object selected = orderingTreeModel.getSelection();
		orderingTreeModel.setOldParent();

		return selected;
	}

	/**
	 * Gets the objects of selected nodes
	 * 
	 * @return	list of selected objects
	 */
	@SuppressWarnings("unchecked")
	public List getSelectedObjects() {
		List nodes = (List) getSelection();
		List objects = new ArrayList();

		Iterator it = nodes.iterator();
		while (it.hasNext()) {
			SelectableTreeNode node = (SelectableTreeNode) it.next();
			objects.add(node.getUserObject());
		}
		return objects;
	}

	/*
	 * @see de.consideo.gui.tools.ISelection
	 *      #setSelection(java.lang.Object)
	 */
	public void setSelection(Object selection) {
		if (selection instanceof List) {
			deselectAll();
			List list = (List) selection;
			Iterator it = list.iterator();
			while (it.hasNext()) {
				Object o = it.next();
				if (o instanceof SelectableTreeNode) {
					SelectableTreeNode node = (SelectableTreeNode) o;
					setNodeSelected(node, true);
				}
			}
			updateMessageArea();
		}
	}

	/**
	 * @return the presentation of this control
	 */
	public JComponent getPresentation() {
		return presentation;
	}

	public JComponent getMessageComponent() {
		return new JScrollPane(messageArea);
	}

	/**
	 * Refresh the control
	 * 
	 * @param what
	 */
	public void refresh(Object what) {
		if (what instanceof List)
			setSelection(what);
		presentation.revalidate();
		presentation.repaint();
	}

	/**
	 * Destructor of the control
	 */
	public void dispose() {
		this.root = null;
		this.orderingTreeModel = null;
		this.selectionTree.removeMouseListener(selectionTreeListener);
		this.orderingTree.removeMouseListener(orderingTreeListener);
		this.toggle.removeActionListener(toggleListener);
		this.moveDown.removeActionListener(downListener);
		this.moveUp.removeActionListener(upListener);
		this.moveLeft.removeActionListener(leftListener);
		this.moveRight.removeActionListener(rightListener);
	}

	/*
	 * @see de.consideo.gui.tools.ISelection
	 *      #addSelectionListener(javax.swing.event.ChangeListener)
	 */
	public void addSelectionListener(ChangeListener l) {
	}

	/*
	 * @see de.consideo.gui.tools.ISelection
	 *      #removeSelectionListener(javax.swing.event.ChangeListener)
	 */
	public void removeSelectionListener(ChangeListener l) {
	}

	/**
	 * create three panel: 2 header panel and middle button panel
	 */
	private void createPanels() {
		// selection header panel
		selectionHeaderPane = new JPanel();
		selectionHeaderPane.setLayout(new BorderLayout());
		selectionToolBar = new JToolBar();
		selectionToolBar.setFloatable(false);
		selectionHeaderPane.add(selectionToolBar, BorderLayout.EAST);
		selectionHeaderLabel = new JLabel(selectionHeader);
		selectionHeaderPane.add(selectionHeaderLabel, BorderLayout.WEST);
		selectionHeaderPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5,
				0));

		// ordering header panel
		orderingHeaderPane = new JPanel();
		orderingHeaderPane.setLayout(new BorderLayout());
		orderingToolBar = new JToolBar();
		orderingToolBar.setFloatable(false);
		orderingHeaderPane.add(orderingToolBar, BorderLayout.EAST);
		orderingHeaderLabel = new JLabel(orderingHeader);
		orderingHeaderPane.add(orderingHeaderLabel, BorderLayout.WEST);
		orderingHeaderPane.setBorder(BorderFactory
				.createEmptyBorder(0, 0, 5, 0));

		middleButtonPane = new JPanel();
		middleButtonPane.setLayout(new BorderLayout());
		
		
		// create buttons
		moveUp = new JButton();
		URL imageURL = getClass().getResource("search_prev.gif");
		if (imageURL != null)
			moveUp.setIcon(new ImageIcon(imageURL));
		else
			moveUp.setText("up"); //$NON-NLS-1$
		moveUp.addActionListener(upListener);

		moveDown = new JButton();
		imageURL = getClass().getResource("search_next.gif"); //$NON-NLS-1$
		if (imageURL != null)
			moveDown.setIcon(new ImageIcon(imageURL));
		else
			moveDown.setText("down"); //$NON-NLS-1$
		moveDown.addActionListener(downListener);

		toggle = new JToggleButton();
		imageURL = getClass().getResource("filter_ps.gif"); //$NON-NLS-1$
		if (imageURL != null)
			toggle.setIcon(new ImageIcon(imageURL));
		else
			toggle.setText("toggle"); //$NON-NLS-1$
		toggle.addActionListener(toggleListener);

		moveRight = new JButton();
		imageURL = getClass().getResource("Forward.gif"); //$NON-NLS-1$
		if (imageURL != null)
			moveRight.setIcon(new ImageIcon(imageURL));
		else
			moveRight.setText(">"); //$NON-NLS-1$
		moveRight.addActionListener(rightListener);

		moveLeft = new JButton();
		imageURL = getClass().getResource("Backward.gif"); //$NON-NLS-1$
		if (imageURL != null)
			moveLeft.setIcon(new ImageIcon(imageURL));
		else
			moveLeft.setText("<"); //$NON-NLS-1$
		moveLeft.addActionListener(leftListener);

		selectAll = new JButton();
		imageURL = getClass().getResource("selectAll.gif"); //$NON-NLS-1$
		if (imageURL != null)
			selectAll.setIcon(new ImageIcon(imageURL));
		else
			selectAll.setText(">>"); //$NON-NLS-1$
		selectAll.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				selectAll();
			}
		});

		deselectAll = new JButton();
		imageURL = getClass().getResource("deselectAll.gif"); //$NON-NLS-1$
		if (imageURL != null)
			deselectAll.setIcon(new ImageIcon(imageURL));
		else
			deselectAll.setText("<<"); //$NON-NLS-1$
		deselectAll.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				deselectAll();
			}
		});
	}

	/**
	 * 
	 * @param visible
	 */
	public void setSelectionRootVisible(boolean visible) {
		if (selectionTree != null) {
			selectionTree.setRootVisible(visible);
		}
	}

	/**
	 * Creates selection and ordering tree control
	 * 
	 * @param root
	 */
	private void createTrees(SelectableTreeNode root) {
		if (root != null)
			selectionTree = new JTree(root);
		else {
			selectionTree = new JTree(new DefaultMutableTreeNode());
			selectionTree.setRootVisible(false);
		}

		selectionTree.getSelectionModel().setSelectionMode(
				TreeSelectionModel.SINGLE_TREE_SELECTION);
		selectionTree.putClientProperty("JTree.lineStyle", "Angled"); //$NON-NLS-1$//$NON-NLS-2$
		selectionTree.setShowsRootHandles(true);
		selectionTree.setCellRenderer(new SelectableTreeNodeRenderer());
		selectionScrollPane = new JScrollPane(selectionTree);

		if (root != null) {
			orderingTreeModel = new OrderingTreeModel(root);
			orderingTree = new JTree(orderingTreeModel);
		} else {
			orderingTree = new JTree(new DefaultMutableTreeNode());
		}

		orderingTree.getSelectionModel().setSelectionMode(
				TreeSelectionModel.SINGLE_TREE_SELECTION);
		orderingTree.putClientProperty("JTree.lineStyle", "Angled"); //$NON-NLS-1$//$NON-NLS-2$
		orderingTree.setShowsRootHandles(true);
		orderingTree.setRootVisible(false);
		orderingTree.setCellRenderer(new SelectableTreeNodeRenderer());
		
		
		orderingScrollPane = new JScrollPane(orderingTree);
	}

	/**
	 * 	    orderable 	 showOrdering
	 *   1.   false      	false
	 *   2.   false      	true
	 *   3.   true       	false
	 *   4.   true       	true
	 */
	private void createPresentation() {
		presentation = new JPanel();
		presentation.setLayout(new BorderLayout());

		if (!orderable) { // 1, 2
			presentation.add(selectionHeaderPane, BorderLayout.NORTH);
			selectionTree.addMouseListener(selectionTreeListener);
			presentation.add(selectionScrollPane, BorderLayout.CENTER);
		} else if (!showOrdering) { // 3
			moveUp.setEnabled(false);
			moveUp.setVisible(false);
			moveDown.setEnabled(false);
			moveDown.setVisible(false);
			selectionToolBar.add(moveUp);
			selectionToolBar.add(moveDown);
			selectionToolBar.add(toggle);
			presentation.add(selectionHeaderPane, BorderLayout.NORTH);

			selectionTree.addMouseListener(selectionTreeListener);
			orderingTree.addMouseListener(orderingTreeListener);
			presentation.add(selectionScrollPane, BorderLayout.CENTER);
		} else { // 4
			selectionTree.addMouseListener(selectionTreeListener);
			orderingTree.getSelectionModel().setSelectionMode(
					TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
			FormLayout layout = new FormLayout(
					"164dlu, 13dlu, pref, 13dlu, 168dlu", //$NON-NLS-1$
					"10dlu,5dlu,14dlu,13dlu,2dlu,13dlu,2dlu,13dlu,2dlu,13dlu,2dlu,13dlu,2dlu,13dlu,14dlu"); //$NON-NLS-1$

			CellConstraints cc = new CellConstraints();
			PanelBuilder builder = new PanelBuilder(layout);

			builder.add(selectionHeaderPane, cc.xy(1, 1));
			builder.add(selectionScrollPane, cc.xywh(1, 3, 1, 13));
			builder.add(orderingHeaderPane, cc.xy(5, 1));
			builder.add(orderingScrollPane, cc.xywh(5, 3, 1, 13));
			builder.add(moveUp, cc.xy(3, 4));
			builder.add(selectAll, cc.xy(3, 6));
			builder.add(moveRight, cc.xy(3, 8));
			builder.add(moveLeft, cc.xy(3, 10));
			builder.add(deselectAll, cc.xy(3, 12));
			builder.add(moveDown, cc.xy(3, 14));

			presentation = builder.getPanel();
		}
		setLayout(new BorderLayout());
		add(presentation);
	}

	/**
	 * Select or deselect a node, update selectionTree and orderingTree
	 * 		1. update selectionTree
	 * 		2. update orderingTree
	 * 
	 * @param node 	
	 * 			the node to be selected or deselected
	 * @param selected
	 */
	public void setNodeSelected(SelectableTreeNode node, boolean selected) {
		// update selection tree
		orderingTreeModel.setOldParent();
		node.setSelected(selected);

		DefaultTreeModel model = ((DefaultTreeModel) selectionTree.getModel());
		SelectableTreeNode updated = node;
		while (updated != null) {
			model.nodeChanged(updated);
			updated = (SelectableTreeNode) updated.getParent();
		}

		// udpate ordering tree
		List nodes = node.getOrderableChildren();
		orderingTreeModel.setThisParent();
		orderingTreeModel.refresh(nodes);
		orderingTreeModel.nodeStructureChanged(orderingTreeModel.orderingRoot);
	}

	private void updateMessageArea() {
		List selected = orderingTreeModel.getSelection();
		String message = "SELECTED ELEMENTS :"; //$NON-NLS-1$
		for (int i = 0; i < selected.size(); i++) {
			message += "\n" + selected.get(i).toString(); //$NON-NLS-1$
		}
		messageArea.setText(message);
	}

	/** 
	 * This listener is only for situation 1, 2 and 3
	 */
	private MouseListener selectionTreeListener = new MouseAdapter() {
		public void mouseClicked(MouseEvent e) {
			if (orderingTreeModel == null) {
				return;
			}

			orderingTreeModel.setOldParent();
			int x = e.getX();
			int y = e.getY();
			int row = selectionTree.getRowForLocation(x, y);
			TreePath path = selectionTree.getPathForRow(row);

			if (path != null) {
				SelectableTreeNode node = (SelectableTreeNode) path
						.getLastPathComponent();
				setNodeSelected(node, !node.getSelected());
				updateMessageArea();
			}
		}
	};
	private MouseListener orderingTreeListener = new MouseAdapter() {
		public void mouseClicked(MouseEvent e) {
			if (e.getClickCount() <= 1)
				return;

			int x = e.getX();
			int y = e.getY();
			int row = orderingTree.getRowForLocation(x, y);
			TreePath path = orderingTree.getPathForRow(row);

			if (path != null) {
				SelectableTreeNode node = (SelectableTreeNode) path
						.getLastPathComponent();
				setNodeSelected(node, !node.getSelected());
				updateMessageArea();
			}
		}
	};
	private ActionListener toggleListener = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			boolean selected = toggle.isSelected();

			selectionHeaderLabel.setText(selected ? orderingHeader
					: selectionHeader);
			moveUp.setEnabled(selected);
			moveUp.setVisible(selected);
			moveDown.setEnabled(selected);
			moveDown.setVisible(selected);

			// hide a tree control and show another tree control
			JComponent comp = selected ? orderingScrollPane
					: selectionScrollPane;
			JComponent oldComp = selected ? selectionScrollPane
					: orderingScrollPane;
			presentation.remove(oldComp);
			presentation.add(comp, BorderLayout.CENTER);
			presentation.invalidate();
			presentation.repaint();
		}
	};
	private ActionListener upListener = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			TreePath path = orderingTree.getSelectionPath();
			if (path != null) {
				SelectableTreeNode node = (SelectableTreeNode) path
						.getLastPathComponent();
				if (!node.getOrderable())
					return;
			}

			int[] rows = orderingTree.getSelectionRows();
			if (rows != null && rows.length > 0) {
				orderingTreeModel.moveUp(rows[0]);
				orderingTreeModel
						.nodeStructureChanged(orderingTreeModel.orderingRoot);
				orderingTree.setSelectionPath(path);
				orderingTree.scrollPathToVisible(path);
				updateMessageArea();
			}
		}
	};
	private ActionListener downListener = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			TreePath path = orderingTree.getSelectionPath();
			if (path != null) {
				SelectableTreeNode node = (SelectableTreeNode) path
						.getLastPathComponent();
				if (!node.getOrderable())
					return;
			}

			int[] rows = orderingTree.getSelectionRows();
			if (rows != null && rows.length > 0) {
				orderingTreeModel.moveDown(rows[0]);
				orderingTreeModel
						.nodeStructureChanged(orderingTreeModel.orderingRoot);
				orderingTree.setSelectionPath(path);
				orderingTree.scrollPathToVisible(path);
				updateMessageArea();
			}
		}
	};
	private ActionListener rightListener = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			TreePath path = selectionTree.getSelectionPath();
			if (path != null) {
				SelectableTreeNode node = (SelectableTreeNode) path
						.getLastPathComponent();
				setNodeSelected(node, true);
				updateMessageArea();
			}
		}
	};
	private ActionListener leftListener = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			TreePath[] paths = orderingTree.getSelectionPaths();
			int cursor = orderingTree.getMaxSelectionRow();
			for (int i = 0; (paths != null) && i < paths.length; i++) {
				TreePath path = paths[i];
				if (path != null) {
					SelectableTreeNode node = (SelectableTreeNode) path
							.getLastPathComponent();
					setNodeSelected(node, false);
					updateMessageArea();
				}
			}
			int count = orderingTree.getRowCount();
			orderingTree.setSelectionRow(cursor < count ? cursor : count - 1);
		}
	};

	private class OrderingTreeModel extends DefaultTreeModel {

		private ImmutableTreeNode orderingRoot;

		public OrderingTreeModel(SelectableTreeNode root) {
			super(root);
			orderingRoot = new ImmutableTreeNode();
			setOrderingRoot(root);
			setRoot(orderingRoot);
		}

		public void moveUp(int index) {
			orderingRoot.moveUp(index);
		}

		public void moveDown(int index) {
			orderingRoot.moveDown(index);
		}

		public void setOldParent() {
			orderingRoot.setOldParent();
		}

		public void setThisParent() {
			orderingRoot.setThisParent();
		}

		public void refresh(List nodes) {
			Iterator it = nodes.iterator();
			while (it.hasNext()) {
				SelectableTreeNode node = (SelectableTreeNode) it.next();
				if (node.getOrderable()) {
					orderingRoot.refresh(node);
				}
			}
		}

		public List getSelection() {
			List result = new ArrayList();
			getSelection(orderingRoot, result);
			return result;
		}

		@SuppressWarnings("unchecked")
		private void getSelection(SelectableTreeNode node, List result) {
			
			
			if (node.getOrderable()) {
				if(node.getState() != TristateCheckBox.NOT_SELECTED)
					result.add(node);
				if(!node.getAllowsChildren())
					return;
			}
			Enumeration en = node.children();
			while (en.hasMoreElements()) {
				SelectableTreeNode child = (SelectableTreeNode) en
						.nextElement();
				getSelection(child, result);
			}
		}

		/**
		 * Recursive get orderable and selected nodes
		 * 
		 * @param node
		 *            root node
		 */
		private void setOrderingRoot(SelectableTreeNode node) {
			if (node.getOrderable()) {
				if (node.getState() != TristateCheckBox.NOT_SELECTED){
					
					Enumeration enumeration = orderingRoot.children();
					boolean exist = false;
					while (enumeration.hasMoreElements()){
						SelectableTreeNode cnode = (SelectableTreeNode) enumeration.nextElement();
						if(cnode.getUserObject().toString().equals(node.getUserObject().toString())){exist = true;break;}
					}
					if(!exist)
						orderingRoot.add(node);
				}	
				if (!node.getAllowsChildren()) {
					return;
				}
			}

			Enumeration enumeration = node.children();
			while (enumeration.hasMoreElements())
				setOrderingRoot((SelectableTreeNode) enumeration.nextElement());
		}
	}

	/**
	 * Getter for the tree model
	 * @return The tree model
	 */
	public OrderingTreeModel getOrderingTreeModel() {
		return orderingTreeModel;
	}
}
